/**
 * Copyright (c) 2006
 *      OpenAVS Developers. All Rights Reserved. test on 20080916
 *
 * Copyright (c) 2005-2006
 *      NSCC. All Rights Reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/**
 * ! \file "loopfilter.c"
 *   \brief Functions related to loop filter.
 */

#include "global.h"
#include "loopfilter.h"

static void DeblockMb_BsV00_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsV10_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsV01_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsV11_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE* pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH00_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE* pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH01_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH10_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE* pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH11_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsV00_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset,
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsV10_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH00_Chroma(
		AVS_INT Bs, 
		MBINFO* pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);
static void DeblockMb_BsH01_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride);

/*
 *   BsH00    BsH01
 * ---------------------
 * |        |          |
 * |BsV00   |BsV01     |
 * |        |          |
 * | BsH10  | BsH11    |
 * ---------------------
 * |        |          |
 * |BsV10   |BsV11     |
 * |        |          |
 * |        |          |
 * ---------------------
 */
static void DeblockVBs2_Luma(
		AVS_BYTE* pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE * p = pStart;
	for (i = 0; i < 8; i++) {
		AVS_BYTE p2 = *(p - 3);
		AVS_BYTE p1 = *(p - 2);
		AVS_BYTE p0 = *(p - 1);

		AVS_BYTE q0 = *p;
		AVS_BYTE q1 = *(p + 1);
		AVS_BYTE q2 = *(p + 2);
		if ((abs(p0 - q0) < Alpha) && 
		    (abs(p1 - p0) < Beta) && 
		    (abs(q1 - q0) < Beta)) {
			AVS_INT ap = abs(p2 - p0);
			AVS_INT aq = abs(q2 - q0);

			if ((ap < Beta) && (abs(p0 - q0) <((Alpha >> 2) + 2))) {
				*(p - 1) = (p1 + 2 * p0 + q0 + 2) >> 2;
				*(p - 2) = (2 * p1 + p0 + q0 + 2) >> 2;
			}
			else {
				*(p - 1) = (2 * p1 + p0 + q0 + 2) >> 2;
			}

			if ((aq < Beta) && (abs(p0 - q0) < ((Alpha >> 2) + 2))) {
				*(p + 0) = (q1 + 2 * q0 + p0 + 2) >> 2;
				*(p + 1) = (2 * q1 + q0 + p0 + 2) >> 2;
			}
			else {
				*(p + 0) = (2 * q1 + q0 + p0 + 2) >> 2;
			}
		}

		p += iStride;
	} 
}


static void DeblockVBs1_Luma(
		AVS_BYTE* pStart,
		AVS_INT C, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_INT ap;
	AVS_INT aq;
	AVS_BYTE * p = pStart;

	for (i = 0; i < 8; i++) {
		AVS_BYTE p2 = *(p - 3);
		AVS_BYTE p1 = *(p - 2);
		AVS_BYTE p0 = *(p - 1);

		AVS_BYTE q0 = *(p + 0);
		AVS_BYTE q1 = *(p + 1);
		AVS_BYTE q2 = *(p + 2);

		if ((abs(p0 - q0) < Alpha) && 
		    (abs(p1 - p0) < Beta) && 
		    (abs(q1 - q0) < Beta)) {
			AVS_INT delta = Clip3(-C, C, 
			                      (((q0 - p0) * 3 + (p1 - q1) + 4) >> 3));

			*(p - 1) = Clip(p0 + delta);
			*(p - 0) = Clip(q0 + delta);

			ap = abs(p2 - p0);
			aq = abs(q2 - q0);

			if (ap < Beta)
				*(p - 2) = Clip(p1 + 
				                Clip3(-C, C, 
				                (((*(p - 1) - p1) * 3 + (p2 - *(p)) + 4) >> 3)));
			if (aq < Beta)
				*(p + 1) = Clip(q1 -
				                Clip3(-C, C, 
				                (((q1 - *(p)) * 3 + (*(p - 1) - q2) + 4) >> 3)));
		}

		p += iStride;
	}  
}

static void DeblockHBs2_Luma(
		AVS_BYTE * pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE* p = pStart;
	for (i = 0; i < 8; i++) {
		AVS_BYTE p2 = *(p - 3 * iStride);
		AVS_BYTE p1 = *(p - 2 * iStride);
		AVS_BYTE p0 = *(p - 1 * iStride);

		AVS_BYTE q0 = *(p + 0 * iStride);
		AVS_BYTE q1 = *(p + 1 * iStride);
		AVS_BYTE q2 = *(p + 2 * iStride);
		if ((abs(p0 - q0) < Alpha) && 
		    (abs(p1 - p0) < Beta) && 
		    (abs(q1 - q0) < Beta)) {
			AVS_INT ap = abs(p2 - p0);
			AVS_INT aq = abs(q2 - q0);

			if ((ap < Beta) && (abs(p0 - q0) < ((Alpha >> 2) + 2))) {
				*(p - 1 * iStride) = (p1 + 2 * p0 + q0 + 2) >> 2;
				*(p - 2 * iStride) = (2 * p1 + p0 + q0 + 2) >> 2;
			}
			else {
				*(p - iStride) = (2 * p1 + p0 + q0 + 2) >> 2;
			}
			if ((aq < Beta) && (abs(p0 - q0) < ((Alpha >> 2) + 2))) {
				*(p + 0 * iStride) = (q1 + 2 * q0 + p0 + 2) >> 2;
				*(p + 1 * iStride) = (2 * q1 + q0 + p0 + 2) >> 2;
			}
			else {
				*(p) = (2 * q1 + q0 + p0 + 2) >> 2;
			}
		}
		p++;
	}
}

static void DeblockHBs1_Luma(
		AVS_BYTE * pStart,
		AVS_INT C, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_INT ap;
	AVS_INT aq;
	AVS_BYTE * p = pStart;
	for (i = 0; i < 8; i++) {
		AVS_BYTE p2 = *(p - 3 * iStride);
		AVS_BYTE p1 = *(p - 2 * iStride);
		AVS_BYTE p0 = *(p - 1 * iStride);

		AVS_BYTE q0 = *p;
		AVS_BYTE q1 = *(p + 1 * iStride);
		AVS_BYTE q2 = *(p + 2 * iStride);

		if ((abs(p0 - q0) < Alpha) && 
		    (abs(p1 - p0) < Beta) && 
		    (abs(q1 - q0) < Beta)) {
			AVS_INT delta = 
				Clip3(-C, C, (((q0 - p0) * 3 + (p1 - q1) + 4) >> 3));

			*(p - iStride) = Clip(p0 + delta);
			*(p ) = Clip(q0 + delta);

			ap = abs(p2 - p0);
			aq = abs(q2 - q0);

			if (ap < Beta)
				*(p - 2 * iStride) = 
					Clip(p1 + 
					     Clip3(-C, C, 
					           (((*(p - iStride) - p1) * 3 + 
					              (p2-*(p)) + 4) >> 3)));
			if (aq < Beta)
				*(p + iStride) = 
					Clip(q1 -
					     Clip3(-C, C, 
					           (((q1 - *(p)) * 3 + 
					             (*(p - iStride) - q2) + 4) >> 3)));
		}
		p++;
	}
}

static void DeblockVBs2_Chroma(
		AVS_BYTE * pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE * p = pStart;

	for (i = 0; i < 4; i++) {
		AVS_BYTE p2 = *(p - 3);
		AVS_BYTE p1 = *(p - 2);
		AVS_BYTE p0 = *(p - 1);

		AVS_BYTE q0 = *(p + 0);
		AVS_BYTE q1 = *(p + 1);
		AVS_BYTE q2 = *(p + 2);
		if ((abs(p0 - q0) < Alpha) && 
                    (abs(p1 - p0) < Beta) && 
                    (abs(q1 - q0) < Beta)) {
			AVS_INT ap = abs(p2 - p0);
			AVS_INT aq = abs(q2 - q0);

			if ((ap < Beta) && (abs(p0 - q0) < ((Alpha >> 2) + 2))) {
				*(p - 1) = (p1 + 2 * p0 + q0 + 2) >> 2;
			}
			else {
				*(p - 1) = (2 * p1 + p0 + q0 + 2) >> 2;
			}
			if ((aq < Beta) && (abs(p0 - q0) < ((Alpha >> 2) + 2))) {
				*(p ) = (q1 + 2 * q0 + p0 + 2) >> 2;
			}
			else {
				*(p ) = (2 * q1 + q0 + p0 + 2) >> 2;
			}
		}

		p += iStride;
	}
}

static void DeblockVBs1_Chroma(
		AVS_BYTE * pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT C, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE * p = pStart;
	for (i = 0; i < 4; i++) {
		AVS_BYTE p2 = *(p - 3);
		AVS_BYTE p1 = *(p - 2);
		AVS_BYTE p0 = *(p - 1);

		AVS_BYTE q0 = *p;
		AVS_BYTE q1 = *(p + 1);
		AVS_BYTE q2 = *(p + 2);

		if (abs(p0 - q0) < Alpha && 
		    abs(p1 - p0) < Beta && 
		    abs(q1 - q0) < Beta) {   
			AVS_INT delta = Clip3(-C, C, 
			                      (((q0 - p0) * 3 + 
			                        (p1 - q1) + 4) >> 3));

			*(p - 1) = Clip(p0 + delta);
			*(p  ) = Clip(q0 + delta);
		}    

		p += iStride;
	}
}

static void DeblockHBs2_Chroma(
		AVS_BYTE * pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE * p = pStart;
	for (i = 0; i < 4; i++) {
		AVS_BYTE p2 = *(p - 3 * iStride);
		AVS_BYTE p1 = *(p - 2 * iStride);
		AVS_BYTE p0 = *(p - iStride);

		AVS_BYTE q0 = *p;
		AVS_BYTE q1 = *(p + iStride);
		AVS_BYTE q2 = *(p + 2 * iStride);
		if (abs(p0 - q0) < Alpha && 
		    abs(p1 - p0) < Beta && 
		    abs(q1 - q0) < Beta) {
			AVS_INT ap = abs(p2 - p0);
			AVS_INT aq = abs(q2 - q0);

			if (ap < Beta && abs(p0 - q0) < ((Alpha >> 2) + 2))
				*(p - iStride) = (p1 + 2 * p0 + q0 + 2) >> 2;
			else
				*(p - iStride) = (2 * p1 + p0 + q0 + 2) >> 2;

			if (aq < Beta && abs(p0 - q0) < ((Alpha >> 2) + 2))
				*(p  ) = (q1 + 2*q0 + p0 + 2) >> 2;
			else
				*(p  ) = (2*q1 + q0 + p0 + 2) >> 2;
		}      
		p ++;
	}
}

static void DeblockHBs1_Chroma(
		AVS_BYTE * pStart, 
		AVS_INT Alpha, AVS_INT Beta, 
		AVS_INT C, AVS_INT iStride)
{
	AVS_INT i;
	AVS_BYTE * p = pStart;
	for (i = 0; i < 4; i++) {
		AVS_BYTE p1 = *(p - 2 * iStride);
		AVS_BYTE p0 = *(p - iStride);

		AVS_BYTE q0 = *p;
		AVS_BYTE q1 = *(p + iStride);
		if (abs(p0 - q0) < Alpha && abs(p1 - p0) < Beta && 
		    abs(q1 - q0) < Beta) {   
			AVS_INT delta = Clip3(-C, C, 
			                      (((q0 - p0) * 3 + 
			                        (p1-q1) + 4) >> 3));

			*(p - iStride) = Clip(p0 + delta);
			*(p  ) = Clip(q0 + delta);
		}
		p++;
	}
}

AVS_INT GetStrengthP(
		AVS_DWORD dwRefIdxP, AVS_DWORD dwRefIdxQ, 
		MOTIONVECTOR * pMvP, MOTIONVECTOR * pMvQ)
{
	if (dwRefIdxP != dwRefIdxQ ||
	    abs(pMvP->x - pMvQ->x) >= 4 ||
	    abs(pMvP->y - pMvQ->y) >= 4)
		return 1;
	return 0;
}

AVS_INT GetStrengthB(
		MOTIONVECTOR * pMvP, MOTIONVECTOR * pMvQ, 
		MOTIONVECTOR * pMvBwP, MOTIONVECTOR * pMvBwQ)
{
	if (abs(pMvP->x - pMvQ->x) >= 4 ||
	    abs(pMvP->y - pMvQ->y) >= 4 ||
	    abs(pMvBwP->x - pMvBwQ->x) >= 4 ||
	    abs(pMvBwP->y - pMvBwQ->y) >= 4)
		return 1;
	return 0;
}

/**
 * Function: Filtering for luma BsV00.
 *
 * Check if BsV00 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV00_Luma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO * pMbP = &(pMbInfo[dwMbIndex-1]);
	MBINFO * pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE* p = pImgData + imgY * iStride + imgX;
	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsV10.
 *
 * Check if BsV10 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV10_Luma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO * pMbP = &(pMbInfo[dwMbIndex - 1]);
	MBINFO * pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE* p = pImgData + (imgY + 8) * iStride + imgX;
	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsV01.
 *
 * Check if BsV01 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV01_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav =  pMbP->dwMbQp;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE * p = pImgData + imgY*iStride + (imgX + 8);

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsV11.
 *
 * Check if BsV11 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV11_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = pMbP->dwMbQp;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE * p = pImgData + (imgY + 8) * iStride + (imgX + 8);

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsH00.
 *
 * Check if BsH00 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH00_Luma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO * pMbP = &(pMbInfo[dwMbIndex - dwMbWidth]);
	MBINFO * pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav+iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav+iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex%dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex/dwMbWidth) << 4;

	AVS_BYTE * p = pImgData + imgY * iStride + imgX;
	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockHBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockHBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsH01.
 *
 * Check if BsH01 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH01_Luma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex-dwMbWidth]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE* p = pImgData + imgY * iStride + (imgX + 8);
	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockHBs2_Luma(p, Alpha, Beta, iStride);
	else if(Bs == 1)
		DeblockHBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsH10.
 *
 * Check if BsH10 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH10_Luma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = pMbP->dwMbQp;
	AVS_INT IndexA = Clip3(0, 63, QPav+iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav+iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE* p = pImgData + (imgY + 8)*iStride + imgX;

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockHBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockHBs1_Luma(p, C, Alpha, Beta, iStride);
}

/**
 * Function: Filtering for luma BsH11.
 *
 * Check if BsH11 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH11_Luma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = pMbP->dwMbQp;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 4;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 4;

	AVS_BYTE * p = pImgData + (imgY + 8) * iStride + (imgX + 8);

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockHBs2_Luma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockHBs1_Luma(p, C, Alpha, Beta, iStride);
}


/**
 * Function: Filtering for chroma BsV00.
 *
 * Check if BsV00 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV00_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex-1]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 3;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 3;

	AVS_BYTE* p = pImgData + imgY * iStride + imgX;

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Chroma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Chroma(p, Alpha, Beta, C, iStride);
}

/**
 * Function: Filtering for chroma BsV10.
 *
 * Check if BsV10 side is inside the boundary before invoking.
 */
static void DeblockMb_BsV10_Chroma(
		AVS_INT Bs, MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex - 1]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 3;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 3;

	AVS_BYTE * p = pImgData + (imgY + 4) * iStride + imgX;

	AVS_INT C = CLIP_TABLE[IndexA];

	if (Bs == 2)
		DeblockVBs2_Chroma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockVBs1_Chroma(p, Alpha, Beta, C, iStride);
}

/**
 * Function: Filtering for chroma BsH00.
 *
 * Check if BsH00 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH00_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, AVS_INT iStride)
{
	MBINFO* pMbP = &(pMbInfo[dwMbIndex - dwMbWidth]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);

	AVS_INT QPav = (pMbP->dwMbQp + pMbQ->dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 3;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 3;

	AVS_BYTE * p = pImgData + imgY * iStride + imgX;
	AVS_INT C = CLIP_TABLE[IndexA];
	if (Bs == 2)
		DeblockHBs2_Chroma(p, Alpha, Beta,iStride);
	else if (Bs == 1)
		DeblockHBs1_Chroma(p, Alpha, Beta, C, iStride);
}

/**
 * Function: Filtering for chroma BsH01.
 *
 * Check if BsH01 side is inside the boundary before invoking.
 */
static void DeblockMb_BsH01_Chroma(
		AVS_INT Bs, 
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		AVS_INT iImgType, 
		AVS_INT iAlphaOffset, AVS_INT iBetaOffset, 
		AVS_BYTE * pImgData, 
		AVS_INT iStride)
{

	MBINFO* pMbP = &(pMbInfo[dwMbIndex - dwMbWidth]);
	MBINFO* pMbQ = &(pMbInfo[dwMbIndex]);


	AVS_INT QPav = (pMbInfo[dwMbIndex - dwMbWidth].dwMbQp + 
	                pMbInfo[dwMbIndex].dwMbQp + 1) / 2;
	AVS_INT IndexA = Clip3(0, 63, QPav + iAlphaOffset);
	AVS_INT IndexB = Clip3(0, 63, QPav + iBetaOffset);
	AVS_INT Alpha = ALPHA_TABLE[IndexA];
	AVS_INT Beta = BETA_TABLE[IndexB];

	AVS_INT imgX = (dwMbIndex % dwMbWidth) << 3;
	AVS_INT imgY = (dwMbIndex / dwMbWidth) << 3;

	AVS_BYTE * p = pImgData + imgY * iStride + (imgX + 4);

	AVS_INT C = CLIP_TABLE[IndexA];
	if (Bs == 2)
		DeblockHBs2_Chroma(p, Alpha, Beta, iStride);
	else if (Bs == 1)
		DeblockHBs1_Chroma(p, Alpha, Beta, C, iStride);
}

static AVS_INT GetBsH00(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;

	if (pMbP->dwMbType == I_8x8 || pMbQ->dwMbType == I_8x8)
		Bs = 2;
	else  {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[2], 
			                  pMbQ->dwMbReferenceIndex[0], 
			                  &(pMbP->mv[2]), &(pMbQ->mv[0]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[2]), &(pMbQ->mv[0]), 
			                  &(pMbP->mvBw[2]), &(pMbQ->mvBw[0]));
	}
	return Bs;
}

static AVS_INT GetBsH01(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	int Bs = 0;
	if (pMbP->dwMbType == I_8x8 || pMbQ->dwMbType == I_8x8)
		Bs = 2;
	else  {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[3], 
			                  pMbQ->dwMbReferenceIndex[1], 
			                  &(pMbP->mv[3]), &(pMbQ->mv[1]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[3]), &(pMbQ->mv[1]), 
			                  &(pMbP->mvBw[3]), &(pMbQ->mvBw[1]));
	}
	return Bs;
}

static AVS_INT GetBsH10(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;
	if (pMbP->dwMbType == I_8x8)
		Bs = 2;
	else {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[0], 
			                  pMbQ->dwMbReferenceIndex[2], 
			                  &(pMbP->mv[0]), &(pMbQ->mv[2]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[0]), &(pMbQ->mv[2]), 
			                  &(pMbP->mvBw[0]), &(pMbQ->mvBw[2]));
	}
	return Bs;
}

static AVS_INT GetBsH11(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;
	if (pMbP->dwMbType == I_8x8)
		Bs = 2;
	else {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[1], 
			                  pMbQ->dwMbReferenceIndex[3], 
			                  &(pMbP->mv[1]), &(pMbQ->mv[3]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[1]), &(pMbQ->mv[3]), 
			                  &(pMbP->mvBw[1]), &(pMbQ->mvBw[3]));
	}
	return Bs;

}

static AVS_INT GetBsV00(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;

	if (pMbP->dwMbType == I_8x8 || pMbQ->dwMbType == I_8x8)
		Bs = 2;
	else {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[1], 
			                  pMbQ->dwMbReferenceIndex[0], 
			                  &(pMbP->mv[1]), &(pMbQ->mv[0]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[1]), &(pMbQ->mv[0]), 
			                  &(pMbP->mvBw[1]), &(pMbQ->mvBw[0]));
	}
	return Bs;
}

static AVS_INT GetBsV01(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;
	if (pMbP->dwMbType == I_8x8)
		Bs = 2;
	else  {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[0], 
			                  pMbQ->dwMbReferenceIndex[1], 
			                  &(pMbP->mv[0]), &(pMbQ->mv[1]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[0]), &(pMbP->mv[1]), 
			                  &(pMbQ->mvBw[0]), &(pMbQ->mvBw[1]));
	}
	return Bs;
}

static AVS_INT GetBsV10(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;

	if (pMbP->dwMbType == I_8x8 || pMbQ->dwMbType == I_8x8)
		Bs = 2;
	else {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[3], 
			                  pMbQ->dwMbReferenceIndex[2], 
			                  &(pMbP->mv[3]), &(pMbQ->mv[2]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[1]), &(pMbQ->mv[2]), 
			                  &(pMbP->mvBw[1]), &(pMbQ->mvBw[2]));
	}
	return Bs;
}

static AVS_INT GetBsV11(MBINFO* pMbP, MBINFO* pMbQ, AVS_INT iImgType)
{
	AVS_INT Bs;
	if (pMbP->dwMbType == I_8x8)
		Bs = 2;
	else {
		if (iImgType == P_IMG)
			Bs = GetStrengthP(pMbP->dwMbReferenceIndex[2], 
			                  pMbQ->dwMbReferenceIndex[3], 
			                  &(pMbP->mv[2]), &(pMbQ->mv[3]));
		else /* B frame */
			Bs = GetStrengthB(&(pMbP->mv[2]), &(pMbQ->mv[3]), 
			                  &(pMbP->mvBw[2]), &(pMbQ->mvBw[3]));
	}
	return Bs;
}

void DeblockOneMacroBlock(
		MBINFO * pMbInfo, 
		AVS_DWORD dwMbIndex, 
		AVS_DWORD dwMbWidth, 
		STREAMINFO * pStrmInfo, 
		VIDEODATA * pCurrVD)
{
	AVS_BOOL bUpMbAvailable = FALSE;
	AVS_BOOL bLeftMbAvailable = FALSE;
	AVS_INT iLumaStride = pStrmInfo->SeqInfo.dwWidth;
	AVS_INT iChromaStride = pStrmInfo->SeqInfo.dwWidth / 2;
	AVS_DWORD dwImgType = pStrmInfo->ImgInfo.dwImageType;
	AVS_INT iAlphaOffset = pStrmInfo->ImgInfo.iAlphaCOffset;
	AVS_INT iBetaOffset = pStrmInfo->ImgInfo.iBetaOffset;

	if (dwMbIndex/dwMbWidth != 0)
		bUpMbAvailable = TRUE;
	if (dwMbIndex%dwMbWidth != 0)
		bLeftMbAvailable = TRUE;
	if (bLeftMbAvailable) {
		AVS_INT Bs00 = GetBsV00(&(pMbInfo[dwMbIndex - 1]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs01 = GetBsV01(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs10 = GetBsV10(&(pMbInfo[dwMbIndex - 1]), 
		                        &(pMbInfo[dwMbIndex]), dwImgType);
		AVS_INT Bs11 = GetBsV11(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);

		DeblockMb_BsV00_Luma(Bs00, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsV01_Luma(Bs01, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsV10_Luma(Bs10, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsV11_Luma(Bs11, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);

		DeblockMb_BsV00_Chroma(Bs00, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->u, iChromaStride);
		DeblockMb_BsV10_Chroma(Bs01, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->u, iChromaStride);

		DeblockMb_BsV00_Chroma(Bs10, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->v, iChromaStride);
		DeblockMb_BsV10_Chroma(Bs11, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->v, iChromaStride);
	}
	else {
		AVS_INT Bs01 = GetBsV01(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs11 = GetBsV11(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);

		DeblockMb_BsV01_Luma(Bs01, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsV11_Luma(Bs11, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);    
	}
	if (bUpMbAvailable) {
		AVS_INT Bs00 = GetBsH00(&(pMbInfo[dwMbIndex - dwMbWidth]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs01 = GetBsH01(&(pMbInfo[dwMbIndex - dwMbWidth]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs10 = GetBsH10(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), dwImgType);
		AVS_INT Bs11 = GetBsH11(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		DeblockMb_BsH00_Luma(Bs00, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsH01_Luma(Bs01, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsH10_Luma(Bs10, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsH11_Luma(Bs11, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);

		DeblockMb_BsH00_Chroma(Bs00, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->u, iChromaStride);
		DeblockMb_BsH01_Chroma(Bs01, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->u, iChromaStride);

		DeblockMb_BsH00_Chroma(Bs00, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->v, iChromaStride);
		DeblockMb_BsH01_Chroma(Bs01, pMbInfo, dwMbIndex, 
		                       dwMbWidth, dwImgType, 
		                       iAlphaOffset, iBetaOffset, 
		                       pCurrVD->v, iChromaStride);

	}
	else {
		AVS_INT Bs10 = GetBsH10(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);
		AVS_INT Bs11 = GetBsH11(&(pMbInfo[dwMbIndex]), 
		                        &(pMbInfo[dwMbIndex]), 
		                        dwImgType);

		DeblockMb_BsH10_Luma(Bs10, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);
		DeblockMb_BsH11_Luma(Bs11, pMbInfo, dwMbIndex, 
		                     dwMbWidth, dwImgType, 
		                     iAlphaOffset, iBetaOffset, 
		                     pCurrVD->y, iLumaStride);    
	}
}

